package com.programmingteam.wallpaperslideshow.ui;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.util.Pair;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.TranslateAnimation;

import com.programmingteam.wallpaperslideshow.Config;
import com.programmingteam.wallpaperslideshow.R;
import com.programmingteam.wallpaperslideshow.contentprovider.ImageProvider.ImagesTable;
import com.programmingteam.wallpaperslideshow.ui.fragments.GalleryFragment;

/**
 * Main dependencies:
 * com.programmingteam.wallpaperslideshow.ui.GalleryActivity
 * com.programmingteam.wallpaperslideshow.ui.fragments.GalleryFragment
 * android.support.v4.view.ViewPager
 * android.support.v4.view.PagerAdapter
 * @author Jakub Skierbiszewski
 */
public class GalleryActivity extends BaseActivity implements ViewPager.OnPageChangeListener {
	public static final String TAG = "WallpaperSlideshow";
	private GalleryFragmentAdapter mGalleryFragmentAdapter;
	private ImageLoader mImageLoader;
	
	//Slider section
	private int mSliderLastPosition = 0;
	
	/**
	 * Receives message from service that new image was downloaded 
	 * and notifies view attached to GalleryFragmentAdapter
	 */
	private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			Log.d(TAG, "GalleryActivity - received broadcast");
			if(GalleryActivity.this.mGalleryFragmentAdapter!=null) {
				GalleryActivity.this.mGalleryFragmentAdapter.notifyDataSetChanged();
			}
		}
	};
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		ViewPager viewPager;

		super.onCreate(savedInstanceState);

		//Start image loading thread
		HandlerThread thread;
		thread = new HandlerThread("ImageLoader", Process.THREAD_PRIORITY_BACKGROUND);
		thread.start();
		mImageLoader = new ImageLoader(thread.getLooper());

		//Initialize views
		setContentView(R.layout.image_gallery);
		getActivityHelper().setupActionBar("Recent", 0);

		if (mGalleryFragmentAdapter == null) {
			mGalleryFragmentAdapter = new GalleryFragmentAdapter(getSupportFragmentManager());
		}
		viewPager = (ViewPager) findViewById(R.id.viewPager);
		viewPager.setPageMargin(6);
		viewPager.setOffscreenPageLimit(3);
		viewPager.setAdapter(mGalleryFragmentAdapter);
		viewPager.setOnPageChangeListener(this);

		mGalleryFragmentAdapter.notifyDataSetChanged();
	}
	
	@Override
	protected void onResume () {
		super.onResume();
		IntentFilter filter = new IntentFilter();
		filter.addAction(Config.Service.BROADCAST_ACTION_ON_DOWNLOADED);
		LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(mReceiver, filter);
	}
	
	@Override
	public void onWindowFocusChanged (boolean hasFocus) {
		super.onWindowFocusChanged (hasFocus);
		onPageSelected(mSliderLastPosition);
	}
	
	@Override
	protected void onPause () {
		LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(mReceiver);
		super.onPause();
	}
	
	@Override
	public void onDestroy() {
		mImageLoader.getLooper().quit();
		super.onDestroy();
	}
	
	/**
	 * Async image loader
	 */
	private final class ImageLoader extends Handler {
		public static final int MSG_READIMAGEPATHS = 1;
		public static final int MSG_LOADIMAGEBITMAPFROMPATH = 2;
		
		public ImageLoader(Looper looper) {
			super(looper);
		}

		@Override
		public void handleMessage(Message msg) {
			int startPos, imgCount, current;
			GalleryFragment galleryFragment;
			Cursor c;
			File imageFile;

			galleryFragment = (GalleryFragment) msg.obj;
			startPos = msg.arg1;
			imgCount = msg.arg2;
			c = managedQuery(ImagesTable.CONTENT_URI, null, "PHOTO_FILE is not null", null, "_ID desc");
			current = 0;
			
			if (c.moveToPosition(startPos)) {
				try {
					do {
						imageFile = new File(c.getString(c.getColumnIndex(ImagesTable.PHOTO_FILE)));
						galleryFragment.setImage(startPos + current, decodeImage(imageFile));
						++current;
					}
					while (c.moveToNext() && current < imgCount);
				}
				catch (IllegalStateException e) { //Activity was killed, which invalidated cursor c
					System.gc();
				}
			}
			
			for(; current<imgCount; current++) {
				galleryFragment.setImage(startPos + current, null);
			}
			c.close();
		}
		
		private Bitmap decodeImage(File imageFile) {
			BitmapFactory.Options o;
			int downsample, width, height;
			Bitmap b = null;
			
			try {
				o = new BitmapFactory.Options();
				o.inJustDecodeBounds = true;
				BitmapFactory.decodeStream(new FileInputStream(imageFile), null, o);
				width = o.outWidth;
				height = o.outHeight;
				downsample = 1;

				while (width / downsample > 200 && height / downsample > 200) {
					downsample *= 2;
				}
				o = new BitmapFactory.Options();
				o.inSampleSize = downsample;
				b = BitmapFactory.decodeStream(new FileInputStream(imageFile), null, o);
			}
			catch (FileNotFoundException e) {}
			return b;
		}
	}

	/**
	 * This class provides initialized fragments for ViewPager.
	 */
	public class GalleryFragmentAdapter extends FragmentPagerAdapter {
		private int mItemsCount;
		//private PagerAdapter.DataSetObserver mObserver;
		
		public GalleryFragmentAdapter(FragmentManager fm) {
			super(fm);
			Cursor c;
			c = managedQuery(ImagesTable.CONTENT_URI, null, "PHOTO_FILE is not null", null, null);
			mItemsCount = (int) ((c.getCount()+8)/6);
			c.close();
		}

		@Override
		public Fragment getItem(int position) {
			GalleryFragment galleryFragment;
			galleryFragment = new GalleryFragment(position == 0 ? 0 : 6 * position - 3);
			galleryFragment.setRetainInstance(true);
			
			Log.d(TAG, "GalleryFragmentAdapter: returning "+position+" view.");
			return galleryFragment;
		}

		@Override
		public int getCount() {
			return mItemsCount;
		}
		
		@Override
		public int getItemPosition(Object object) {

			//Refresh images!!
			return PagerAdapter.POSITION_NONE;
	    }
	}
	
	/**
	 * Starts async images paths read
	 * @param callback GalleryFragmet, which setImages() method will be called after loading images
	 * @param startPos Images start position
	 * @param imgCount Images count
	 */
	public void loadImagePathsAsync(GalleryFragment callback, int startPos, int imgCount) {
		Message msg;
		
		msg = mImageLoader.obtainMessage();
		msg.arg1 = startPos;
		msg.arg2 = imgCount;
		msg.obj = callback;
		mImageLoader.sendMessage(msg);
	}
	
	@Override
	public void onPageSelected(int position) {
		TranslateAnimation anim;
		int delta;
		View sliderView, sliderBarView;
		
		if(mGalleryFragmentAdapter.getCount()<2) return;
		
		sliderView = findViewById(R.id.gallery_slider);
		sliderBarView = findViewById(R.id.gallery_slider_bar);
		
		delta = sliderBarView.getWidth() - sliderView.getWidth();
		delta = delta/(mGalleryFragmentAdapter.getCount()-1);
		
		anim = new TranslateAnimation(delta*mSliderLastPosition, delta*position, 0, 0);
		anim.setDuration(100);
		anim.setInterpolator(new AccelerateDecelerateInterpolator());
		anim.setFillAfter(true);
		sliderView = findViewById(R.id.gallery_slider);
		sliderView.startAnimation(anim);
		mSliderLastPosition = position;
	}

	@Override
	public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
	
	@Override
	public void onPageScrollStateChanged(int state) {}
}